/**
 * 报表设计公司(2011)
 */
package com.reportgear.designer.pane.style;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.abbp.report.context.ReportContext;
import net.abbp.report.model.Cell;
import net.abbp.report.model.cell.style.FontStyle;
import net.abbp.report.view.GridView;

import com.reportgear.core.swing.pane.base.JBasePane;
import com.reportgear.designer.ui.base.ColorSelectionPane;
import com.reportgear.designer.ui.base.JLineComboBox;
import com.reportgear.designer.ui.base.JNumberField;
import com.reportgear.designer.util.GUIConstants;
import com.reportgear.report.context.DefaultValues;
import com.reportgear.report.view.grid.util.GraphHelper;

/**
 * @version 1.0 2011-3-24
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 */
public class ReportFontPane extends JBasePane implements ICellStyle {

	private JTextField familyField;
	private JList familyList;
	private JNumberField sizeField;
	private JList sizeList;
	private JTextField styleField;
	private JList styleList;
	private ColorSelectionPane foregroundColorPane;
	private JLineComboBox underlineCombo;
	private JCheckBox isStrikethroughCheckBox;
	private JCheckBox isShadowCheckBox;
	private JCheckBox isSuperscriptCheckBox;
	private JCheckBox isSubscriptCheckBox;
	private PreivewArea preview;
	private EventListenerList eventChangeList = new EventListenerList();
	ActionListener actionListener = new ActionListener() {

		public void actionPerformed(ActionEvent paramActionEvent) {
			fireStateChanged();
		}
	};
	ChangeListener changeListener = new ChangeListener() {

		public void stateChanged(ChangeEvent paramChangeEvent) {
			fireStateChanged();
		}
	};
	ListSelectionListener listSelectionListener = new ListSelectionListener() {

		public void valueChanged(ListSelectionEvent paramListSelectionEvent) {
			fireStateChanged();
		}
	};
	DocumentListener documentListener = new DocumentListener() {

		public void changedUpdate(DocumentEvent paramDocumentEvent) {
			fireStateChanged();
		}

		public void insertUpdate(DocumentEvent paramDocumentEvent) {
			fireStateChanged();
		}

		public void removeUpdate(DocumentEvent paramDocumentEvent) {
			fireStateChanged();
		}
	};

	public ReportFontPane() {
		initComponents();
	}

	protected void initComponents() {
		this.setLayout(new BorderLayout());
		this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
		JPanel fontInfoPane = new JPanel();
		fontInfoPane.setLayout(new BoxLayout(fontInfoPane, 0));
		this.familyField = new JTextField();
		JPanel fontPane = createTextFieldListPane("名字", this.familyField, this.familyList = new JList(
				GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()));
		this.familyField.setEditable(false);
		this.familyList.setVisibleRowCount(4);
		this.familyList.addListSelectionListener(this.listSelectionListener);

		fontInfoPane.add(fontPane);
		fontInfoPane.add(Box.createHorizontalStrut(6));

		this.styleField = new JTextField();
		JPanel stylePane = createTextFieldListPane("样式", this.styleField, this.styleList = new JList(new String[] {
				"普通", "加粗", "斜体", "加粗斜体" }));
		this.styleField.setEditable(false);
		this.styleList.setVisibleRowCount(4);
		this.styleList.addListSelectionListener(this.listSelectionListener);

		fontInfoPane.add(stylePane);
		fontInfoPane.add(Box.createHorizontalStrut(6));

		this.sizeField = new JNumberField();
		JPanel sizePane = createTextFieldListPane("大小", this.sizeField, this.sizeList = new JList(new Integer[] { 6, 8,
				9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 }));
		this.sizeField.setMaxDecimalLength(0);
		this.sizeField.getDocument().addDocumentListener(this.documentListener);
		this.sizeField.getDocument().addDocumentListener(new DocumentListener() {

			public void changedUpdate(DocumentEvent paramDocumentEvent) {
				updatePreviewLabel();
			}

			public void insertUpdate(DocumentEvent paramDocumentEvent) {
				updatePreviewLabel();
			}

			public void removeUpdate(DocumentEvent paramDocumentEvent) {
				updatePreviewLabel();
			}
		});
		this.sizeList.setVisibleRowCount(4);
		this.sizeList.addListSelectionListener(this.listSelectionListener);
		fontInfoPane.add(sizePane);

		add(fontInfoPane, BorderLayout.NORTH);

		JPanel pane = new JPanel();
		add(pane, BorderLayout.CENTER);
		pane.setLayout(new BorderLayout(4, 4));

		JPanel effectPane = new JPanel();
		pane.add(effectPane, BorderLayout.WEST);
		effectPane.setLayout(new BorderLayout());
		effectPane.setBorder(BorderFactory.createTitledBorder("特殊效果"));
		JPanel effectInnerPane = new JPanel();
		effectPane.add(effectInnerPane, BorderLayout.NORTH);
		effectInnerPane.setLayout(new GridLayout(4, 1));
		this.isStrikethroughCheckBox = new JCheckBox("删除线");
		this.isStrikethroughCheckBox.addChangeListener(this.changeListener);
		this.isStrikethroughCheckBox.setMnemonic('K');
		this.isShadowCheckBox = new JCheckBox("阴影");
		this.isShadowCheckBox.addChangeListener(this.changeListener);
		this.isShadowCheckBox.setMnemonic('S');
		this.isSuperscriptCheckBox = new JCheckBox("上标");
		this.isSuperscriptCheckBox.addChangeListener(this.changeListener);
		this.isSuperscriptCheckBox.setMnemonic('E');
		this.isSubscriptCheckBox = new JCheckBox("下标");
		this.isSubscriptCheckBox.addChangeListener(this.changeListener);
		this.isSubscriptCheckBox.setMnemonic('B');
		effectInnerPane.add(getLeftJustPane(this.isStrikethroughCheckBox));
		effectInnerPane.add(getLeftJustPane(this.isShadowCheckBox));
		effectInnerPane.add(getLeftJustPane(this.isSuperscriptCheckBox));
		effectInnerPane.add(getLeftJustPane(this.isSubscriptCheckBox));

		JPanel pane1 = new JPanel();
		pane.add(pane1, BorderLayout.CENTER);
		pane1.setLayout(new BorderLayout());
		JPanel pane2 = new JPanel();
		pane1.add(pane2, BorderLayout.NORTH);
		pane2.setLayout(new GridLayout(1, 2, 0, 0));
		JPanel underlinePane = new JPanel();
		pane2.add(underlinePane);
		underlinePane.setBorder(BorderFactory.createTitledBorder("下划线"));
		underlinePane.setLayout(new BorderLayout());
		this.underlineCombo = new JLineComboBox(GUIConstants.UnderlineStyleArray);
		this.underlineCombo.addActionListener(this.actionListener);
		underlinePane.add(this.underlineCombo, BorderLayout.CENTER);
		JPanel forecolorPane = new JPanel();
		pane2.add(forecolorPane);
		forecolorPane.setLayout(new BorderLayout());
		forecolorPane.setBorder(BorderFactory.createTitledBorder("字体颜色"));
		this.foregroundColorPane = new ColorSelectionPane(120);
		this.foregroundColorPane.addColorChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent paramChangeEvent) {
				ReportFontPane.this.fireStateChanged();
			}
		});
		forecolorPane.add(this.foregroundColorPane, BorderLayout.CENTER);
		this.preview = new PreivewArea();
		this.preview.setBorder(BorderFactory.createTitledBorder("预览"));
		pane1.add(this.preview, BorderLayout.CENTER);

		this.isSuperscriptCheckBox.addChangeListener(this.changeListener);
		this.isSuperscriptCheckBox.addChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent paramChangeEvent) {
				if (!(isSuperscriptCheckBox.isSelected())) {
					return;
				}
				isSubscriptCheckBox.setSelected(false);
			}
		});
		this.isSubscriptCheckBox.addChangeListener(this.changeListener);
		this.isSubscriptCheckBox.addChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent paramChangeEvent) {
				if (!(isSubscriptCheckBox.isSelected())) {
					return;
				}
				isSuperscriptCheckBox.setSelected(false);
			}
		});
	}

	public void addChangeListener(ChangeListener listener) {
		this.eventChangeList.add(ChangeListener.class, listener);
	}

	public void fireStateChanged() {
		Object[] arrayOfObject = this.eventChangeList.getListenerList();
		ChangeEvent localChangeEvent = null;
		for (int i = arrayOfObject.length - 2; i >= 0; i -= 2) {
			if (arrayOfObject[i] != ChangeListener.class) {
				continue;
			}
			if (localChangeEvent == null) {
				localChangeEvent = new ChangeEvent(this);
			}
			((ChangeListener) arrayOfObject[(i + 1)]).stateChanged(localChangeEvent);
		}
	}

	private JPanel getLeftJustPane(JComponent c) {
		JPanel pane = new JPanel();
		pane.setLayout(new BorderLayout());
		pane.add(c, BorderLayout.CENTER);
		pane.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));

		return pane;
	}

	public void populate(FontStyle reportFont) {
		this.familyList.setSelectedValue(reportFont.getName(), true);
		this.familyField.setText(reportFont.getName());
		this.styleList.setSelectedIndex(reportFont.getStyle());
		this.styleField.setText(reportFont.getFontName());
		this.sizeList.setSelectedValue(new Integer(reportFont.getSize()), true);
		this.sizeField.setValue(reportFont.getSize());
		this.foregroundColorPane.setColor(reportFont.getForeground());
		this.underlineCombo.setSelectedLineStyle(reportFont.getUnderline());
		this.isStrikethroughCheckBox.setSelected(reportFont.isStrikethrough());
		this.isShadowCheckBox.setSelected(reportFont.isShadow());
		this.isSuperscriptCheckBox.setSelected(reportFont.isSuperscript());
		this.isSubscriptCheckBox.setSelected(reportFont.isSubscript());
		ListHandler localListHandler = new ListHandler();
		this.familyList.addListSelectionListener(localListHandler);
		this.styleList.addListSelectionListener(localListHandler);
		this.sizeList.addListSelectionListener(localListHandler);
		ActionListener listener1 = new ActionListener() {

			public void actionPerformed(ActionEvent evt) {
				updatePreviewLabel();
			}
		};
		this.isStrikethroughCheckBox.addActionListener(listener1);
		this.isShadowCheckBox.addActionListener(listener1);
		this.isSuperscriptCheckBox.addActionListener(listener1);
		this.isSubscriptCheckBox.addActionListener(listener1);
		this.underlineCombo.addItemListener(new ItemListener() {

			public void itemStateChanged(ItemEvent evt) {
				updatePreviewLabel();
			}
		});
		this.foregroundColorPane.addColorChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent evt) {
				updatePreviewLabel();
			}
		});
		updatePreviewLabel();
	}

	public FontStyle update() {
		return FontStyle.getInstance(this.familyField.getText(), this.styleList.getSelectedIndex(),
				(int) this.sizeField.getValue(), this.foregroundColorPane.getColor(), this.underlineCombo
						.getSelectedLineStyle(), this.isStrikethroughCheckBox.isSelected(), this.isShadowCheckBox
						.isSelected(), this.isSuperscriptCheckBox.isSelected(), this.isSubscriptCheckBox.isSelected());
	}

	private JPanel createTextFieldListPane(String labelStr, JTextField textField, JList listInfo) {
		GridBagLayout layout = new GridBagLayout();
		JPanel retPane = new JPanel(layout);
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.gridwidth = 1;
		constraints.gridheight = 1;
		constraints.fill = GridBagConstraints.BOTH;
		constraints.weightx = 1.0D;
		JLabel label = new JLabel(labelStr);
		layout.setConstraints(label, constraints);
		retPane.add(label);
		constraints.gridy = 1;
		Component c = Box.createVerticalStrut(0);
		layout.setConstraints(c, constraints);
		retPane.add(c);
		constraints.gridy = 2;
		layout.setConstraints(textField, constraints);
		retPane.add(textField);
		constraints.gridy = 3;
		c = Box.createVerticalStrut(2);
		layout.setConstraints(c, constraints);
		retPane.add(c);
		constraints.gridy = 4;
		constraints.gridheight = 0;
		constraints.weighty = 1.0D;
		JScrollPane scrollPane = new JScrollPane(listInfo);
		layout.setConstraints(scrollPane, constraints);
		retPane.add(scrollPane);

		return retPane;
	}

	private void updatePreviewLabel() {
		this.preview.setPaintFont(update());
	}

	public void populateCellStyle(GridView workSheet) {
		FontStyle reportFont = workSheet.getActiveCellStyle().getFontStyle();

		if (reportFont == null) {
			DefaultValues defValues = ReportContext.INSTANCE.getDefaultValues();
			populate(defValues.getReportFont());
		} else {
			populate(reportFont);
		}
	}

	public void updateCellStyle(GridView workSheet) {
		FontStyle font = update();
		if (font.equals(workSheet.getActiveCellStyle().getFontStyle())) {
			return;
		}

		List<Cell> cells = workSheet.getSelectedCells();
		for (Cell cell : cells) {
			cell.setStyle(cell.getStyle().deriveReportFont(font));
		}
	}

	class PreivewArea extends JComponent {

		private String paintText = "Report中国";
		private FontStyle paintFont = null;

		public void setPaintFont(FontStyle reportFont) {
			this.paintFont = reportFont;
			repaint();
		}

		@Override
		public void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			Dimension dim = getSize();
			g2.setColor(getBackground());
			GraphHelper.fillRect(g2, 0.0D, 0.0D, dim.width, dim.height);
			if (this.paintFont == null) {
				return;
			}
			FontMetrics fm = getFontMetrics(this.paintFont);
			g2.setColor(this.paintFont.getForeground());
			g2.setFont(this.paintFont);
			int x1 = (dim.width - fm.stringWidth(this.paintText)) / 2;
			int x2 = (dim.width + fm.stringWidth(this.paintText)) / 2;
			int h = (dim.height - fm.getHeight()) / 2 + fm.getAscent();
			GraphHelper.drawLine(g2, 4.0D, h, x1 - 8, h, 1);
			GraphHelper.drawString(g2, this.paintText, x1, h);
			GraphHelper.drawLine(g2, x2 + 8, h, dim.width - 4, h, 1);
		}
	}

	class ListHandler implements ListSelectionListener {

		public void valueChanged(ListSelectionEvent evt) {
			Object o2;
			Object o1 = evt.getSource();
			if (o1 == familyList) {
				o2 = (String) familyList.getSelectedValue();
				if (o2 != null) {
					familyField.setText((String) o2);
				}
			} else if (o1 == sizeList) {
				o2 = (Integer) sizeList.getSelectedValue();
				if (o2 != null) {
					sizeField.setValue(((Integer) o2).intValue());
				}
			} else if (o1 == styleList) {
				o2 = (String) styleList.getSelectedValue();
				if (o2 != null) {
					styleField.setText((String) o2);
				}
			}
			updatePreviewLabel();
		}
	}

	public static void main(String[] args) {
		ReportFontPane pane = new ReportFontPane();
		pane.showDialog(null, "测试", 600, 500);
	}
}
